/*
 * Copyright 2010 Christoph Widulle (christoph.widulle@googlemail.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
 * License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */

package com.android1.amarena2d.actions.base;

import com.android1.amarena2d.animation.Animation;
import com.android1.amarena2d.nodes.behavior.ActionTarget;
import com.android1.amarena2d.nodes.behavior.AnimationTarget;

public class Animate extends IntervalAction {

    private Animation animation;
    private Animation.Frame[] frames;
    private Animation.Frame origFrame;
    private boolean restoreOriginalFrame;
    private AnimationTarget animationTarget;
    private int frameCount;
    private float slice;

    public static Animate $(Animation animation) {
        return new Animate(animation, true);
    }

    public static Animate $(Animation animation, boolean restoreOriginalFrame) {
        return new Animate(animation, restoreOriginalFrame);
    }

    public Animate(Animation animation, boolean restoreOriginalFrame) {
        super(animation.getDuration());
        this.restoreOriginalFrame = restoreOriginalFrame;
        this.animation = animation;
        this.frames = animation.getFrames();
        origFrame = null;
    }

    public Animate reset(Animation animation, boolean restoreOriginalFrame) {
        duration = animation.getDuration();
        this.restoreOriginalFrame = restoreOriginalFrame;
        this.animation = animation;
        origFrame = null;
        this.frames = animation.getFrames();
        return this;
    }


    @Override
    public void start(ActionTarget aTarget) {

        if (!(aTarget instanceof AnimationTarget))
            throw new UnsupportedOperationException("Animation can only be used on HasTexturedMesh targets.");

        frameCount = frames.length;
        slice = 1.0f / frameCount;
        animationTarget = (AnimationTarget) aTarget;
        origFrame = animationTarget.animation().getCurrentFrame();
        super.start(aTarget);
    }

    @Override
    public void stop() {
        if (restoreOriginalFrame) {
            animationTarget.animation().applyFrame(origFrame);
        }
        super.stop();
    }

    @Override
    public void update(float time) {
        int idx = 0;

        if (time != 0)
            idx = (int) (time / slice);

        if (idx >= frameCount) {
            idx = frameCount - 1;
        }

        if (!(animationTarget == (frames[idx]))) {
            animationTarget.animation().applyFrame(frames[idx]);
        }
    }

    public Animation getAnimation() {
        return animation;
    }

    @Override
    public IntervalAction reverse() {
        return Animate.$(animation.copyReverse());
    }

    @Override
    public Animate copy() {
        return Animate.$(animation);
    }
}
